//
//  LoginDelegate.swift
//  imprint
//
//  Created by 小柠檬🍋 on 2025/1/11.
//

import Foundation
import SwiftUI
import LeanCloud

class LoginDelegate<T: LoginProtocol>: BaseViewModel, LoginProtocol{
    
    private let login : T
    private var type = 0 //0 登陆，1绑定
    
    init(login: T) {
        self.login = login
    }
    
    
    func doLogin() {
        type = 0
        login.doLogin()
    }
    
    
    func bind() {
        type = 1
        login.doLogin()
    }
    
    func doAuthSuc(code: String) {
        request{
            let (typeKey,id,newUserBean) =  try await self.login.getAuthInfo(code: code)
            return (typeKey,id,newUserBean)
        } suc: { (typeKey:String,id:String,newUserBean:UserBean) in
            self.doAuthSuc(typeKey: typeKey, id: id, newUserBean: newUserBean)
        } fail: {
            showToast($0.message)
        }
    }
    
    
    func doAuthSuc(access_token: String, openid: String) {
        request{
            let (typeKey,id,newUserBean) =  try await self.login.getAuthInfo(access_token: access_token, openid: openid)
            return (typeKey,id,newUserBean)
        } suc: { (typeKey:String,id:String,newUserBean:UserBean) in
            self.doAuthSuc(typeKey: typeKey, id: id, newUserBean: newUserBean)
           
        } fail: {
            showToast($0.message)
        }
    }
    
    private func doAuthSuc(typeKey:String,id:String,newUserBean:UserBean) {
        switch(self.type) {
        case 0:
            //执行登陆
            self.doLoginAccount(type: typeKey, id: id, newUserBean: newUserBean)
        case 1:
            //执行绑定
            NotificationCenter.default.post(name: .bindAccount, object: (typeKey,id))
        default:break
        }
    }

    
    func getAuthInfo(code: String) async throws -> (String, String, UserBean) {
        return try await login.getAuthInfo(code: code)
    }
    
    func getAuthInfo(access_token: String, openid: String) async throws -> (String, String, UserBean) {
        return try await login.getAuthInfo(access_token: access_token, openid: openid)
    }
    
    func doLoginAccount(type: String, id: String, newUserBean: UserBean) {
        request {
            let user = try await self.queryAccount(type: type, id: id)
            let (new,userBean) = try await self.saveUserBean(type: type, id: id, newUserBean: newUserBean, user: user)
            return (new,userBean)
        } suc: { (new, userBean) in
            userManager.user = nil
            userManager.user = userBean
            userManager.doLogin()
            if new {
                //执行新人赠送
                userManager.requestReceiveCloud(capacityType: 3)
            }
        } fail: {_ in
            showToast("登陆失败")
        }
    }
    
    /**
     * 账号查询
     */
    func queryAccount(type: String, id: String) async throws -> UserBean? {
        let query = LCQuery(className: "User_")
        query.whereKey(type, .equalTo(id))
        return try await retry(maxRetries: 5, retryDelayMillis: 300) {
            return try await LeancloudManager.instance.getFirst(query: query, modeType: UserBean.self)
        }
    }
    
    /**
     * 更新或者上传用户信息
     * @param newUserBean QQ wx登录返回 userBean
     * @param resultUserBean 接口请求后返回的 userBean
     */
    func saveUserBean(type: String, id: String, newUserBean: UserBean, user:UserBean?) async throws -> (Bool,UserBean) {
        if let user = user {
            showLog("有账号")
            //更新账号  ,更新设备id
            return (false,user)
        } else {
            showLog("创建账号")
            let userBean = newUserBean
            userBean.loginType = type
            userBean.aiChatCount = 10
            switch type {
            case LoginType.WX.rawValue:
                userBean.wx = id
            case LoginType.QQ.rawValue:
                userBean.qq = id
            case LoginType.PHONE.rawValue:
                userBean.phone = id
            case LoginType.APPLE.rawValue:
                userBean.apple = id
            case LoginType.TOURIST.rawValue:
                userBean.tourist = id
            default: break
            }
            //保存账号
            return try await retry(maxRetries: 5, retryDelayMillis: 200) {
                let objectId = try await LeancloudManager.instance.saveToId(todo: userBean)
                userBean.objectId = objectId
                return (true,userBean)
            }
        }
    }
    
}
